/* ************************************************************************
   * JBEvaluator.cpp                                                   ****
   *                                                                      *
   * Copyright 2006 Video Poker Tools.                                    *
   * Copyright 2011 Ville Jyrkkä,                                         *
   * M-Poker team (https://github.com/jykae/M-Poker/wiki)                 *
   *                                                                      *
   * This file is part of M-Poker.                                        *
   *                                                                      *
   * M-Poker is free software: you can redistribute it and/or modify      *
   * it under the terms of the GNU General Public License as              *
   * published by the Free Software Foundation, either version 3 of the   *
   * License, or (at your option) any later version.                      *
   *                                                                      *
   * M-Poker is distributed in the hope that it will be useful,           *
   * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
   * GNU General Public License for more details.                         *
   *                                                                      *
   * You should have received a copy of the GNU General Public            *
   * License along with M-Poker.                                          *
   * If not, see <http://www.gnu.org/licenses/>.                          *
   *                                                                      *
   *                                                                      *
   ************************************************************************/

#include "JBevaluator.h"

JBEvaluator::JBEvaluator(void)
{
	for (int i = 0; i < 8192; i++)
	{		
		straightData[i] = 0;
		bitCount[i] = 0;
		for (int j = 0; j < 13; j++)
		{
			if ((i & (1 << j)))
			{
				bitCount[i]++;
			}
		}
	}
	int straights[10] = {4111,31,62,124,248,496,992,1984,3968,7936};
	for (int i = 0; i < 10; i++)
	{
		straightData[straights[i]] = i + 1;
	}
	for (int i = 0; i < 52; i++)
	{
		cardData1[i] = &(rankHash[i / 13]);
		cardData2[i] = 1 << (i % 13);
	}
}

JBEvaluator::~JBEvaluator(void)
{
}

int JBEvaluator::evaluate(int *hand)
{
	rankHash[0] = 0;
	rankHash[1] = 0;
	rankHash[2] = 0;
	rankHash[3] = 0;
	*cardData1[hand[0]] |= cardData2[hand[0]];
	*cardData1[hand[1]] |= cardData2[hand[1]];
	*cardData1[hand[2]] |= cardData2[hand[2]];
	*cardData1[hand[3]] |= cardData2[hand[3]];
	*cardData1[hand[4]] |= cardData2[hand[4]];
	return evaluate();
}

int JBEvaluator::evaluate(void)
{
	//Royal Flush
	for (int i = 0; i < 4; i++)
	{
		if (straightData[rankHash[i]] == 10)
		{
			return ROYAL_FLUSH;
		}
	}
	//Straight Flush
	for (int i = 0; i < 4; i++)
	{
		if (straightData[rankHash[i]])
		{
			return STRAIGHT_FLUSH;
		}
	}
	//Four of a Kind
	int hash4 = rankHash[0] & rankHash[1] & rankHash[2] & rankHash[3];
	if (hash4)
	{
		return FOUR_KIND;
	}
	//Full House
	int hash3 = (rankHash[0] & rankHash[1] & rankHash[2]) | (rankHash[0] & rankHash[1] & rankHash[3]) 
			| (rankHash[0] & rankHash[2] & rankHash[3]) | (rankHash[1] & rankHash[2] & rankHash[3]);
	int hash2 = (rankHash[0] & rankHash[1]) | (rankHash[0] & rankHash[2]) | (rankHash[0] & rankHash[3]) 
			| (rankHash[1] & rankHash[2]) | (rankHash[1] & rankHash[3]) | (rankHash[2] & rankHash[3]);
	if (hash3 && bitCount[hash2] == 2)
	{
		return FULL_HOUSE;
	}
	//Flush
	for (int i = 0; i < 4; i++)
	{
		if (bitCount[rankHash[i]] == 5)
		{
			return FLUSH;
		}
	}
	//Straight
	int hash1 = rankHash[0] | rankHash[1] | rankHash[2] | rankHash[3];
	if (straightData[hash1])
	{
		return STRAIGHT;
	}
	//Three of a Kind
	if (hash3)
	{
		return THREE_KIND;
	}
	//Two Pair
	if (bitCount[hash2] == 2)
	{
		return TWO_PAIR;
	}
	//Jack or Better
	if (hash2 >= (1 << 9))
	{
		return JACK_BETTER;
	}
	//Nothing
	return NOTHING;
}

